#include "easylogging++.h"
#include "ia.h"
#include <string>

INITIALIZE_EASYLOGGINGPP

#define CONFIG_FILE	"ia_log.conf"

void rolloutHandler(const char* filename, std::size_t size)
{
	std::rename(filename, std::string(filename + IA_FORMAT_DATETIME_NOW_MS).c_str());
}

class CLogHelper
{
public:
	CLogHelper() {
		el::Loggers::addFlag(el::LoggingFlag::StrictLogFileSizeCheck);
		el::Configurations conf(CONFIG_FILE);
		el::Loggers::reconfigureAllLoggers(conf);
		el::Helpers::installPreRollOutCallback(rolloutHandler);

	}
	~CLogHelper() {
		el::Helpers::uninstallPreRollOutCallback();
	}
};

CLogHelper _logHelper;
static IA_F_LOG_CALLBACK* _pLogCallback = NULL;
static void* _pUser = NULL;

void ia_log_set_callback(IA_F_LOG_CALLBACK* pcallBack, void* pUser) {
	_pLogCallback = pcallBack;
	_pUser = pUser;
}
	
void ia_log(IA_E_LOG_LEVEL level, char* msg, const char* file, const char* func, int line)
{
	std::string fName = std::string(file);
	std::size_t backslashIdx = fName.find_last_of("\\");
	if (backslashIdx != std::string::npos) {
		fName = fName.substr(backslashIdx +1);
	}

	switch (level)
	{
	case IA_E_LOG_LEVEL::IA_L_DEBUG:	LOG(DEBUG)			<<  fName  << ": "	<< line<< "  |  " << func << "   |   " << msg;	break;
	case IA_E_LOG_LEVEL::IA_L_INFO:		LOG(INFO)			<<  fName  << ": "	<< line<< "  |  " << func << "   |   " << msg; 	break;
	case IA_E_LOG_LEVEL::IA_L_WARN:		LOG(WARNING)		<<  fName  << ": "	<< line<< "  |  " << func << "   |   " << msg; 	break;
	case IA_E_LOG_LEVEL::IA_L_ERROR:	LOG(ERROR)			<<  fName  << ": "	<< line<< "  |  " << func << "   |   " << msg; 	break;
	case IA_E_LOG_LEVEL::IA_L_FATAL:	LOG(FATAL)			<<  fName  << ": "	<< line<< "  |  " << func << "   |   " << msg; 	break;

	default:	LOG(INFO) << msg;				break;
	}

	if (NULL != _pLogCallback) {
		try {
			(*_pLogCallback)(level, fName.c_str(), func, line, msg, _pUser);
		}
		catch (...) {}
	}
}

std::string ia_format_datetime(const char* format, int precision) {
	el::base::SubsecondPrecision ssPrec(precision);
	return el::base::utils::DateTime::getDateTime(format, &ssPrec);
}

int ia_make_dir(std::string& dir)
{
	IA_ASSERT(!dir.empty());

	if (dir.at(dir.length() - 1) != '\\') {
		dir += "\\";
	}

	std::string::size_type pos = dir.find('\\');
	while (pos != std::string::npos) {
		std::string subDir = dir.substr(0, pos);
		DWORD dwAttr = GetFileAttributes(subDir.c_str());
		if (dwAttr == INVALID_FILE_ATTRIBUTES) {
			if (0 != _mkdir(subDir.c_str()) && GetLastError() != EEXIST) {
				IA_ERROR("Failed to make directory %s", dir.c_str());
				IA_RETURN_ERR
			}
		}
		pos = dir.find('\\', pos + 1);
	}

	IA_RETURN_OK
}